using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using PortableDeviceConstants;
using ZuneDeviceConstants;
using PortableDeviceApiLib;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct PropVariant
{
    [FieldOffset(0)]
    public short variantType;
    [FieldOffset(8)]
    public IntPtr pointerValue;
    [FieldOffset(8)]
    public byte byteValue;
    [FieldOffset(8)]
    public long longValue;
} 

namespace zUnlock
{
    public partial class frmMain : Form
    {
        string gDog;
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        static extern int SHCreateStreamOnFile(string pszFile, uint grfMode, out IStream ppstm);

        public delegate void CallbackTest(PortableDeviceApiLib.IPortableDeviceValues pvParameters);
     
        public frmMain()
        {            
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            EnumerateAllDevices();            
        }

        private void EnumerateAllDevices()
        {
            PortableDeviceApiLib.PortableDeviceManagerClass devManager = new PortableDeviceApiLib.PortableDeviceManagerClass();

            uint cDevices = 1;
            string[] deviceIDs = new string[1];
            deviceIDs[0] = string.Empty;
            devManager.GetDevices(ref deviceIDs[0], ref cDevices);

            if (cDevices > 0)
            {
                deviceIDs = new string[cDevices];
                devManager.GetDevices(ref deviceIDs[0], ref cDevices);

                for (int i = 0; i < cDevices; i++)
                {
                    string strTemp = deviceIDs[i];

                    ListViewItem item = new ListViewItem(getDeviceName(ref devManager, strTemp));
                    item.SubItems.Add(getDeviceDescription(ref devManager, strTemp));
                    item.SubItems.Add(getDeviceManufacturer(ref devManager, strTemp));
                    item.SubItems.Add(strTemp);

                    lstWPDs.Items.Add(item);
                    item = null;
                }
            }
            else
            {
                LOG("No Devices Found.");
            }    
        }

        private void StartEnumerateContent(string deviceID)
        {
            PortableDeviceClass device = new PortableDeviceClass();
            IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            IPortableDeviceContent deviceContent;

            clientInfo.SetStringValue(ref PortableDevicePKeys.WPD_CLIENT_NAME, "Zune");
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MAJOR_VERSION, 1);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MINOR_VERSION, 0);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_REVISION, 2);

            device.Open(deviceID, clientInfo);
                      
            device.Content(out deviceContent);

            TreeNode t = new TreeNode();
            t.Text = "DEVICE";
            EnumerateContent(ref deviceContent, "DEVICE", 0, t);            
            
            tvwContent.Nodes.Add(t);

            device.Close();
        }

        private bool EnumerateContent(ref IPortableDeviceContent devContent, string parent, int level,  TreeNode node)
        {        
            bool res = true;
            IEnumPortableDeviceObjectIDs sEnum;

            devContent.EnumObjects(0, parent, null, out sEnum);
            
            while (res)
            {
                string objectID;
                uint f = 0;
                
                sEnum.Next(1,out objectID,ref f);
                    
                if (objectID == null)
                {
                    return false;                
                }
                else
                {  
                    IPortableDeviceKeyCollection contentPropertyKeys = (IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();

                    contentPropertyKeys.Add(ref PortableDevicePKeys.WPD_OBJECT_NAME);
                    contentPropertyKeys.Add(ref PortableDevicePKeys.WPD_OBJECT_SIZE);

                    IPortableDeviceProperties contentProperty;
                    devContent.Properties(out contentProperty);

                    IPortableDeviceValues contentPropertyValues;
                    contentProperty.GetValues(objectID, contentPropertyKeys, out contentPropertyValues);

                    string fileName = "";
                    ulong fileSize = 0;
                    
                    try
                    {
                        contentPropertyValues.GetStringValue(ref PortableDevicePKeys.WPD_OBJECT_NAME, out fileName);
                    }
                    catch { }

                    try
                    {
                        contentPropertyValues.GetUnsignedLargeIntegerValue(ref PortableDevicePKeys.WPD_OBJECT_SIZE, out fileSize);
                    }
                    catch { }
                    TreeNode t = new TreeNode("(" + objectID + ") " + fileName + " [" + fileSize.ToString() + "]");
                    //TreeNode t = new TreeNode(objectID);
                    t.ToolTipText = objectID;                    
                    EnumerateContent(ref devContent, objectID, level + 1, t);
                    node.Nodes.Add(t);
                }
            }
            
            return res;
        }

        private string getDeviceName(ref PortableDeviceApiLib.PortableDeviceManagerClass pDeviceManager, string pnpDeviceID)
        {    
            uint count = 81;
            ushort[] chars = new ushort[count];            
            pDeviceManager.GetDeviceFriendlyName(pnpDeviceID, ref chars[0], ref count);           
            return  ushortTostring(chars);
        }

        private string getDeviceManufacturer(ref PortableDeviceApiLib.PortableDeviceManagerClass pDeviceManager, string pnpDeviceID)
        {
            uint count = 81;
            ushort[] chars = new ushort[count];
            pDeviceManager.GetDeviceManufacturer(pnpDeviceID, ref chars[0], ref count);
            return ushortTostring(chars);
        }

        private string getDeviceDescription(ref PortableDeviceApiLib.PortableDeviceManagerClass pDeviceManager, string pnpDeviceID)
        {
            uint count = 81;
            ushort[] chars = new ushort[count];
            pDeviceManager.GetDeviceDescription(pnpDeviceID, ref chars[0], ref count);
            return ushortTostring(chars);
        }

        private string ushortTostring(ushort[] chars)
        {
            string text = "";
            foreach(ushort x in chars)
            {
                if (x>0) text += (char)x;
            }
            return text;
        }

        public void LOG(string msg)
        {
            txtLog.Text += msg + System.Environment.NewLine;            
        }

        private void lstWPDs_SelectedIndexChanged(object sender, EventArgs e)
        {                        

        }

        private void connectToZune(string pnpDeviceID)
        {              
            PortableDeviceApiLib.PortableDeviceManagerClass pPortableDeviceManager = new PortableDeviceApiLib.PortableDeviceManagerClass();
            pPortableDeviceManager.RefreshDeviceList();            
            
            PortableDeviceApiLib.PortableDeviceClass pPortableDevice = new PortableDeviceApiLib.PortableDeviceClass();
            PortableDeviceApiLib.PortableDeviceClass pPortableDevice2 = new PortableDeviceApiLib.PortableDeviceClass();
            PortableDeviceApiLib.IPortableDeviceCapabilities pCapabilities;
            PortableDeviceApiLib.IPortableDeviceValues pValues = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            PortableDeviceApiLib.IPortableDeviceKeyCollection pCommands = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            PortableDeviceApiLib.IPortableDeviceValues pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();            
            PortableDeviceApiLib.IPortableDeviceValues pResults;
            int err = 0; string te = ""; object z = new object(); string writeContext; string enumContext;
            string storageID = "";

            // [001-002] Connect to Zune
            pValues.SetStringValue(ref PortableDevicePKeys.WPD_CLIENT_NAME, "Zune.exe");
            pValues.SetStringValue(ref PortableDevicePKeys.WPD_CLIENT_EVENT_COOKIE, "Zune.exe");
            pValues.SetStringValue(ref ZuneDevicePKeys.ZUNE_MISC_11, "Zune.exe");
            pValues.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MAJOR_VERSION, 1);
            pValues.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MINOR_VERSION, 3);
            pValues.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_REVISION,0x1660);
            pValues.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, 0x20000);
            pPortableDevice.Open(pnpDeviceID, pValues);           

            // [003] Send Zune Command A18
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();  
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A18.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A18.pid);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0 ) return;

            // [004] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_START_FIND");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_START_FIND.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_START_FIND.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_PARENT_ID, "DEVICE");
            pPortableDevice.SendCommand(0, pParameters, out pResults);            
            pResults.GetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, out enumContext);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [005] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, 1);
            pPortableDevice.SendCommand(0, pParameters, out pResults);            
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // Process Results
            PortableDeviceApiLib.IPortableDevicePropVariantCollection propCollection;
            pResults.GetIPortableDevicePropVariantCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS, out propCollection);            
            uint propCount = 0;
            propCollection.GetCount(ref propCount);
            for (uint x = 0; x < propCount; x++)
            {
                tag_inner_PROPVARIANT propTag = new tag_inner_PROPVARIANT();
                propCollection.GetAt(x, ref propTag);
                IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(propTag));
                Marshal.StructureToPtr(propTag, ptrValue, false);
                PropVariant pv = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
                if (pv.variantType == 31 /*VT_LPWSTR*/) storageID =  Marshal.PtrToStringUni(pv.pointerValue);
                 
                LOG("Storage ID: " + storageID);                
            }

            // [006] Get Supported Commands
            pPortableDevice.Capabilities(out pCapabilities);
            pCapabilities.GetSupportedCommands(out pCommands);
            
            // [007] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, storageID);
            PortableDeviceApiLib.IPortableDeviceKeyCollection keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_FUNCTIONAL_OBJECT_CATEGORY);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [008] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, 1);
            pPortableDevice.SendCommand(0, pParameters, out pResults);            
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [009]
            pCapabilities.GetSupportedCommands(out pCommands);

            // [010] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, "RenderingInformation");
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_FUNCTIONAL_OBJECT_CATEGORY);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [011] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, 1);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 1) return;

            // [012] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_END_FIND");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_END_FIND.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_END_FIND.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [013] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_START_FIND");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_START_FIND.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_START_FIND.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_PARENT_ID, "DEVICE");
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, out enumContext);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [014] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, 1);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [015]
            pCapabilities.GetSupportedCommands(out pCommands);

            // [016] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, storageID);
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_FUNCTIONAL_OBJECT_CATEGORY);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;
            
            //pPortableDevice.Close();
            // [017]
            pPortableDevice2.Open(pnpDeviceID, pValues);

            // [018] Send Zune Command A18
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A18.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A18.pid);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err != 0) return;

            // [019] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_FIND_NEXT.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, 1);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);            
            if (err != 0) return;

            // Process Results           
            pResults.GetIPortableDevicePropVariantCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS, out propCollection);
            propCount = 0; string found = "";
            propCollection.GetCount(ref propCount);
            for (uint x = 0; x < propCount; x++)
            {
                tag_inner_PROPVARIANT propTag = new tag_inner_PROPVARIANT();
                propCollection.GetAt(x, ref propTag);
                IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(propTag));
                Marshal.StructureToPtr(propTag, ptrValue, false);
                PropVariant pv = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
                if (pv.variantType == 31 /*VT_LPWSTR*/) found = Marshal.PtrToStringUni(pv.pointerValue);

                LOG("Found: " + found);
            }

            // [020]
            pCapabilities.GetSupportedCommands(out pCommands);
            
            // [021] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, found);
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_FUNCTIONAL_OBJECT_CATEGORY);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [022] LOG("Sending WPD_COMMAND_OBJECT_ENUMERATION_END_FIND");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_END_FIND.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_ENUMERATION_END_FIND.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, enumContext);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [023]
            pCapabilities.GetSupportedCommands(out pCommands);

            // [024] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, "DEVICE");
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_DEVICE_PROTOCOL);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [025]
            pCapabilities.GetSupportedCommands(out pCommands);

            // [026] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, "DEVICE");
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_DEVICE_PROTOCOL);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            // [027]
            pCapabilities.GetSupportedCommands(out pCommands);

            // [028] LOG("Sending WPD_COMMAND_OBJECT_PROPERTIES_GET");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, PortableDevicePKeys.WPD_COMMAND_OBJECT_PROPERTIES_GET.pid);
            pParameters.SetStringValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_OBJECT_ID, "DEVICE");
            keys = (PortableDeviceApiLib.IPortableDeviceKeyCollection)new PortableDeviceTypesLib.PortableDeviceKeyCollectionClass();
            keys.Add(ref PortableDevicePKeys.WPD_DEVICE_FRIENDLY_NAME);
            pParameters.SetIPortableDeviceKeyCollectionValue(ref PortableDevicePKeys.WPD_PROPERTY_OBJECT_PROPERTIES_PROPERTY_KEYS, keys);
            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;

            ////LOG("Sending ZUNE_COMMAND_A18");
            //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A18.fmtid);
            //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A18.pid);
            //pPortableDevice.SendCommand(0, pParameters, out pResults);

            //pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1014, out te);
            //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            //if (err > 0) return;
                                             
            // [029]* LOG("Sending ZUNE_COMMAND_A11");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A11.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A11.pid);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);

            pResults.GetIUnknownValue(ref ZuneDevicePKeys.ZUNE_RESULT_1005, out z);
            IPortableDevicePropVariantCollection pdpvcc = (IPortableDevicePropVariantCollection)z;

            uint pCount = 0;
            pdpvcc.GetCount(ref pCount);
            for (uint x = 0; x < pCount; x++)
            {
                tag_inner_PROPVARIANT propTag = new tag_inner_PROPVARIANT();
                pdpvcc.GetAt(x, ref propTag);

                IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(propTag));
                Marshal.StructureToPtr(propTag, ptrValue, false);
                PropVariant pv = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
                //LOG("[" + x.ToString() + "] Varaint Type: " + pv.variantType + " Long Value: " + pv.longValue);
            }
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;
          
            // [030]* LOG("Sending ZUNE_COMMAND_A12");
            IPortableDevicePropVariantCollection pvc = (IPortableDevicePropVariantCollection)new PortableDeviceTypesLib.PortableDevicePropVariantCollectionClass();
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A12.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A12.pid);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x9216);
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);

            uint bob;
            pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_CloseSession, out bob);
            pResults.GetIUnknownValue(ref ZuneDevicePKeys.ZUNE_GetStorageIDs, out z);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            if (err > 0) return;
          
            //[031]* LOG("Sending ZUNE_COMMAND_A14");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A14.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A14.pid);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x9212);
            if (err > 0) return;
           
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetObjectHandles, 0x311);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);

            pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_RESULT_1013, out bob);
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out te);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            //[032]* LOG("Sending ZUNE_COMMAND_A16");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A16.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A16.pid);
            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, te);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_ResetDevice, 0x311);

            string leafFile;

            // Static Header        
            leafFile = "0201010000027502000001350100000000b501000000010000000000000000000000000000000000125a756e6520536f6674776172652043412031000100010080336ee6aa07bfb3ffd04024cec38be6497ef60e3d7f682e0ff15e6c65ff613bde176fad7137884e80a813cf53c3101aa51b9e4f54b24fd514cdc509b6b71e1f48513df06444d9b55963e8121c4c69b67d6a1314f973c9585c29bb990ad7fd151dbbcb4f9ed7dfe292ba4ed9c6acf58e6adeef5b877a1c1545742634916946459b094b259ed85ef02b08a318e67afd68c289a8c6a61bc8023ca87fe367bdcc0856c3d15758c866e53fb52e86ec569c9c070a22174fbd7c4dcd395ec68530163451ce1f588044a06ebb95a6d4be68b089a4f25a612ffcea56c1c3f8a6880c0576f26574b64ff83d2868f0fe3696bc8425487ae062d48aadfd088a9787b806810bed000001370100000000b703000000000000000000000000000000000000000000145a756e6520536f667477617265204c6561662031000100010080e577d3fcbe3f03e24fe88c19f46498e1c736181bb2febe2eeb1e2692b6dbd0d183eb2b29b2d33645b8098dc674dd25d2a65edacd16fe8e3dff01b2213aa44f3b2c6836a10356d4241701c2db54749d89777f7a80900f84b29735698c212df5165b5022b5f3bfb6a78bf034e29f9b2b9716d3d329509a95add72d3457c3d4d0ca7eeac9776f4d73a4aafd896baa5a8685c05d5b746665218481675ed629b2553a9df03d745866c5cf240351a76c6dbbd02830e5f472e2ad24587c7cab6018fdd934c093df41cab6187e6e1ee9bb8dd599f9a210f4051fcdfd55288d9761ca22c3219e72247646ab5050b0b2c77f1dfb6f9545640361a27cafcc59f32442e21b7b0010";                                

            // Variable 16 Bytes
            leafFile += "871365e8da0f8f32b238351b31663b56";

            // Static ?
            leafFile += "010080";   

            // Variable 128 Bytes
            leafFile += "43f7051a7773e3fab623953cb33b097053b3a3a3c5e3054cc8f2f0fcccc20fe6a397ed857a06eda55fd983578aed9b7802d04f615a19189a70df873f3ad98913c3a1385fbe2a6cd4f379bdb8ca2ba0bcc7cdfd46e675d67ebe37b8ab4561cad96e925a0754dc0ae0760484f00920f183a88bf63ad735c44fcd3b505d03be197b";           
            byte[] xf = GetLeaf(leafFile); 
            uint p = 0x311;

            pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref xf[0], p);
            
            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_RESULT_1011, out bob);
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out te);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            //[033]*  LOG("Sending ZUNE_COMMAND_A17");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);
            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, te);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);

            pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_CloseSession, out bob);
            pResults.GetIUnknownValue(ref ZuneDevicePKeys.ZUNE_GetStorageIDs, out z);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            //[034]* LOG("Sending ZUNE_COMMAND_A13");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A13.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A13.pid);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x9213);
           
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);

            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            string readContext = "";
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out readContext);

            //[035]* LOG("Sending ZUNE_COMMAND_A15");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A15.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A15.pid);

            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1008, 0x3C8);

            xf = new byte[0x3C8];
            p = 0x3C8;                 
            pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref xf[0], p);

            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            //[036]* LOG("Sending ZUNE_COMMAND_A17");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);
            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            //[037]* LOG("Sending ZUNE_COMMAND_A14");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A14.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A14.pid);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x9212);
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetObjectHandles, 0x14);
            pPortableDevice2.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out writeContext);

            //do{
                //[038]* LOG("Sending ZUNE_COMMAND_A16");
                pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A16.fmtid);
                pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A16.pid);
                
                pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, writeContext);
                pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_ResetDevice, 0x14);



                xf = GetLeaf("02030010b268674dfce326a7383c500f1d7755e3");
                p = 0x14;
                pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref xf[0], p);

                pPortableDevice2.SendCommand(0, pParameters, out pResults);
                pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_RESULT_1011, out bob);
                pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out te);
                pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

                //[039]* LOG("Sending ZUNE_COMMAND_A17");
                pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
                pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);

                pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, writeContext);

                pPortableDevice2.SendCommand(0, pParameters, out pResults);
                pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
                pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_CloseSession, out bob);                
            //} while( bob != 8193);

            //LOG("Sending ZUNE_COMMAND_A13");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A13.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A13.pid);

            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x1015);

            tag_inner_PROPVARIANT stab;
            IntToPropVariant(0xD217,out stab);
            pvc.Add(ref stab);
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out readContext);

            //LOG("Sending ZUNE_COMMAND_A15");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A15.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A15.pid);

            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1008, 0x4);

            xf = new byte[0x4];
            p = 0x4;
            pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref xf[0], p);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); 

            //LOG("Sending ZUNE_COMMAND_A17");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);

            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); 

            //LOG("Sending ZUNE_COMMAND_A13");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A13.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A13.pid);

            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_GetDeviceInfo, 0x9104);

            pvc.Clear();
            IntToPropVariant(0x01, out stab);
            pvc.Add(ref stab);
            IntToPropVariant(0xF0, out stab);
            pvc.Add(ref stab);
            IntToPropVariant(0x00, out stab);
            pvc.Add(ref stab);
            IntToPropVariant(0x64, out stab);
            pvc.Add(ref stab);
            pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_OpenSession, pvc);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); 
            pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out readContext);

            //LOG("Sending ZUNE_COMMAND_A15");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A15.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A15.pid);

            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);
            pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1008, 0x0);

            byte xsf = 0;
            p = 0;
            pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref xsf, p);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); 

            //LOG("Sending ZUNE_COMMAND_A17");
            pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
            pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);

            pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, readContext);

            pPortableDevice.SendCommand(0, pParameters, out pResults);
            pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err);

            LOG("Got to the end!");

            //LOG("Attempting to attach to events");
                //PortableDeviceApiLib.IPortableDeviceEventCallback pCallback;
                //pCallback = new CallbackHandle();
                //string cookie = "";
                //pPortableDevice.Advise(0, pCallback, null, out cookie);
                //LOG("Success. COOKIE: " + cookie);
                //LOG("Looking up commands...");
                //pPortableDevice.Capabilities(out pCapabilities);
                //pCapabilities.GetSupportedCommands(out pCommands);
                //uint count = 0;
                //pCommands.GetCount(ref count);
                //LOG("Found " + count.ToString() + " commands and they are: ");
                //PortableDeviceApiLib._tagpropertykey key = new PortableDeviceApiLib._tagpropertykey();
                //for (int x = 0; x < count; x++)
                //{
                //    pCommands.GetAt((uint)x, ref key);
                //    LOG(x.ToString() + ": " + key.pid.ToString() + "  " + key.fmtid.ToString());
                //    LOG("     Options:");
                //    PortableDeviceApiLib.IPortableDeviceValues pOptions = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                //    pCapabilities.GetCommandOptions(ref key, out pOptions);
                //    uint c = 0;
                //    pOptions.GetCount(ref c);
                //    for (int z = 0; z < c; z++)
                //    {
                //        PortableDeviceApiLib.tag_inner_PROPVARIANT ip = new PortableDeviceApiLib.tag_inner_PROPVARIANT();
                //        pOptions.GetAt((uint)z, ref key, ref ip);
                //        LOG("             " + ip.vt.ToString());
                //    }
                //}
               
                // Send Zune Command A18
                //LOG("Sending ZUNE_COMMAND_A18");

               
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A18.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A18.pid);
                //pPortableDevice.SendCommand(0, pParameters, out pResults);
                
                
                //pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1014, out te); LOG("String: " + te);                
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());

                //// Send Zune Command A11
                //LOG("Sending ZUNE_COMMAND_A11");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();               
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A11.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A11.pid);                
                //pPortableDevice.SendCommand(0, pParameters, out pResults);

                //object z;
                //pResults.GetIUnknownValue(ref ZuneDevicePKeys.ZUNE_RESULT_1005, out z);
                //IPortableDevicePropVariantCollection pdpvcc = (IPortableDevicePropVariantCollection)z;

                //uint propCount = 0;
                //pdpvcc.GetCount(ref propCount);
                //for (uint x = 0; x < propCount; x++)
                //{
                //    tag_inner_PROPVARIANT propTag = new tag_inner_PROPVARIANT();
                //    pdpvcc.GetAt(x, ref propTag);

                //    IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(propTag));
                //    Marshal.StructureToPtr(propTag, ptrValue, false);
                //    PropVariant pv = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
                //    LOG("[" + x.ToString() + "] Varaint Type: " + pv.variantType + " Long Value: " + pv.longValue);
                //}
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());


                // Send Zune Command A14
                //LOG("Sending ZUNE_COMMAND_A14");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A14.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A14.pid);
                //pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1001, 0x9212);
                //IPortableDevicePropVariantCollection pvc = (IPortableDevicePropVariantCollection)new PortableDeviceTypesLib.PortableDevicePropVariantCollectionClass();
                //pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_UKN_1002, (object)pvc);
                //pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1007, 0x311);
                //pPortableDevice.SendCommand(0, pParameters, out pResults);

                //uint bob;
                //pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_RESULT_1013, out bob); LOG("UINT: " + bob.ToString());
                //pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out te); LOG("String: " + te);
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());

                //LOG("Sending ZUNE_COMMAND_A16");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A16.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A16.pid);
                //pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, te);
                //pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1010, 0x311);

                //for (int x = 0x00; x <= 0xFF; x++)
                //{
                //    byte[] pancho = new byte[x + 1]; uint vila = (uint)x;

                //    pParameters.SetBufferValue(ref ZuneDevicePKeys.ZUNE_UKN_1012, ref pancho[0], vila);
                //    pPortableDevice.SendCommand(0, pParameters, out pResults);
                //}

                ////pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_RESULT_1011, out bob); LOG("UINT: " + bob.ToString());
                //pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, out te); LOG("String: " + te);
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());

                //LOG("Sending ZUNE_COMMAND_A17");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A17.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A17.pid);
                //pParameters.SetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1006, te);
                //pPortableDevice.SendCommand(0, pParameters, out pResults);

                //pResults.GetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1003, out bob); LOG("UINT: " + bob);
                //pResults.GetIUnknownValue(ref ZuneDevicePKeys.ZUNE_UKN_1004, out z);                
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());

                //LOG("Sending ZUNE_COMMAND_A13");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A13.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A13.pid);
                //pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1001, 0x9213);
                //pvc = (IPortableDevicePropVariantCollection)new PortableDeviceTypesLib.PortableDevicePropVariantCollectionClass();
                //pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_UKN_1002, (object)pvc);

                //pPortableDevice.SendCommand(0, pParameters, out pResults);

                //pResults.GetStringValue(ref ZuneDevicePKeys.ZUNE_RESULT_1014, out te); LOG("String: " + te);
                //pResults.GetErrorValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT, out err); LOG("HRESULT: " + err.ToString());

                //LOG("Sending Zune Command 12");
                //pParameters = (PortableDeviceApiLib.IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();                
                //pParameters.SetGuidValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_CATEGORY, ref ZuneDevicePKeys.ZUNE_COMMMAND_A12.fmtid);
                //pParameters.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_PROPERTY_COMMON_COMMAND_ID, ZuneDevicePKeys.ZUNE_COMMMAND_A12.pid);
                //pParameters.SetUnsignedIntegerValue(ref ZuneDevicePKeys.ZUNE_UKN_1001, 0x9214);

                //IPortableDevicePropVariantCollection pvc = (IPortableDevicePropVariantCollection)new PortableDeviceTypesLib.PortableDevicePropVariantCollection();
                
                //PropVariant pvValue = new PropVariant();
                //pvValue.variantType = 19;
                //pvValue.longValue = 0xBF09929F;

                //IntPtr ptrValue2 = Marshal.AllocHGlobal(Marshal.SizeOf(pvValue));
                //Marshal.StructureToPtr(pvValue, ptrValue2, false);

                //PortableDeviceApiLib.tag_inner_PROPVARIANT ipValue =
                //    (PortableDeviceApiLib.tag_inner_PROPVARIANT)
                //    Marshal.PtrToStructure(ptrValue2, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));               
                //pvc.Add(ref ipValue);

                //pvValue = new PropVariant();
                //pvValue.variantType = 19;
                //pvValue.longValue = 0x4B7491F4;
                //ptrValue2 = Marshal.AllocHGlobal(Marshal.SizeOf(pvValue));
                //Marshal.StructureToPtr(pvValue, ptrValue2, false);
                //ipValue = (PortableDeviceApiLib.tag_inner_PROPVARIANT)
                //    Marshal.PtrToStructure(ptrValue2, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));
                //pvc.Add(ref ipValue);

                //pvValue = new PropVariant();
                //pvValue.variantType = 19;
                //pvValue.longValue = 0xC8C74C2A;
                //ptrValue2 = Marshal.AllocHGlobal(Marshal.SizeOf(pvValue));
                //Marshal.StructureToPtr(pvValue, ptrValue2, false);
                //ipValue = (PortableDeviceApiLib.tag_inner_PROPVARIANT)
                //    Marshal.PtrToStructure(ptrValue2, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));
                //pvc.Add(ref ipValue);

                //pvValue = new PropVariant();
                //pvValue.variantType = 19;
                //pvValue.longValue = 0xA19C0F2E;
                //ptrValue2 = Marshal.AllocHGlobal(Marshal.SizeOf(pvValue));
                //Marshal.StructureToPtr(pvValue, ptrValue2, false);
                //ipValue = (PortableDeviceApiLib.tag_inner_PROPVARIANT)
                //    Marshal.PtrToStructure(ptrValue2, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));
                //pvc.Add(ref ipValue);
                
                //pParameters.SetIUnknownValue(ref ZuneDevicePKeys.ZUNE_UKN_1002, pvc);
                //pPortableDevice.SendCommand(0, pParameters, out pResults);
                
            //}
            //catch(Exception ex)
            //{
            //    LOG("We have a problem... "  + ex.Message);                
            //}
        }

        private void cmdTest_Click(object sender, EventArgs e)
        {

        }

        static void StringToPropVariant(string value,
        out PortableDeviceApiLib.tag_inner_PROPVARIANT propvarValue)
        {
            // We'll use an IPortableDeviceValues object to transform the
            // string into a PROPVARIANT
            PortableDeviceApiLib.IPortableDeviceValues pValues =
                (PortableDeviceApiLib.IPortableDeviceValues)
                    new PortableDeviceTypesLib.PortableDeviceValuesClass();

            // We insert the string value into the IPortableDeviceValues object
            // using the SetStringValue method
            pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_ID, value);

            // We then extract the string into a PROPVARIANT by using the 
            // GetValue method
            pValues.GetValue(ref PortableDevicePKeys.WPD_OBJECT_ID,
                                        out propvarValue);
        }


        static void IntToPropVariant(uint value, out PortableDeviceApiLib.tag_inner_PROPVARIANT propvarValue)
        {
            // We'll use an IPortableDeviceValues object to transform the
            // string into a PROPVARIANT
            PortableDeviceApiLib.IPortableDeviceValues pValues =
                (PortableDeviceApiLib.IPortableDeviceValues)
                    new PortableDeviceTypesLib.PortableDeviceValuesClass();

            // We insert the string value into the IPortableDeviceValues object
            // using the SetStringValue method
            pValues.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_OBJECT_ID, value);

            // We then extract the string into a PROPVARIANT by using the 
            // GetValue method
            pValues.GetValue(ref PortableDevicePKeys.WPD_OBJECT_ID,
                                        out propvarValue);
        }

        public static byte[] StrToByteArray(string str)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            return encoding.GetBytes(str);
        }


        public byte[] GetLeaf(string str)
        {            
            int discarded;
            byte[] byteArray = Utility.HexEncoding.GetBytes(str, out discarded);          
            return byteArray;            
        }

        private void enumerateContentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lstWPDs.SelectedItems.Count == 0) return;
            gDog = lstWPDs.SelectedItems[0].SubItems[3].Text;
            StartEnumerateContent(lstWPDs.SelectedItems[0].SubItems[3].Text);           
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lstWPDs.SelectedItems.Count == 0) return;            
            connectToZune(lstWPDs.SelectedItems[0].SubItems[3].Text);
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (lstWPDs.SelectedItems.Count == 0) return;            
            transferContent(lstWPDs.SelectedItems[0].SubItems[3].Text, tvwContent.SelectedNode.ToolTipText);
        }


        private void transferContent(string pnpDeviceID, string objectID)
        {
            /************************
             *      Variables                          
             ************************/
            PortableDeviceClass device = new PortableDeviceClass();
            IPortableDeviceResources deviceResources;
            IStream readStream;
            IStream writeStream;                                    
            IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            IPortableDeviceContent deviceContent;
            uint bestTransferSize = 0, bytesWritten = 0, bytesRead = 0, totalBytes = 0;
          

            clientInfo.SetStringValue(ref PortableDevicePKeys.WPD_CLIENT_NAME, "Zune");
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MAJOR_VERSION, 1);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MINOR_VERSION, 0);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_REVISION, 2);

            device.Open(pnpDeviceID, clientInfo);
            device.Content(out deviceContent);
            deviceContent.Transfer(out deviceResources);

            try {
                deviceResources.GetStream(objectID, ref PortableDevicePKeys.WPD_RESOURCE_DEFAULT, 0x00, ref bestTransferSize, out readStream);
            } 
            catch {
                LOG("Problem Accessing Object");
                return; 
            }
 
            byte[] file = new byte[bestTransferSize];
            
            SHCreateStreamOnFile(objectID + ".txt", 0x1001, out writeStream); 
            
            do{ 
                readStream.RemoteRead(out file[0], bestTransferSize,out bytesRead);                                      
                writeStream.RemoteWrite(ref file[0], bytesRead, out bytesWritten);
                totalBytes += bytesWritten;
                writeStream.Commit(0x00);
            } while (bytesRead > 0);

            device.Close();          

            LOG("Wrote (bytes): " + totalBytes.ToString());

            /* Clean Up */
            device = null;
            deviceResources = null;
            readStream = null;
            writeStream = null;
            clientInfo = null;
            deviceContent = null;
            file = null;

            return;
        }

        void uploadContent(string pnpDeviceID, string fileName)
        {
            PortableDeviceClass device = new PortableDeviceClass();
            IPortableDeviceResources deviceResources;
            IStream readStream;
            IStream writeStream;
            string cookie = "";

            uint bestTransferSize = 0;
            uint bytesWritten, bytesRead;
            uint totalBytes = 0;
            IPortableDeviceValues clientInfo = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            IPortableDeviceContent deviceContent;            

            clientInfo.SetStringValue(ref PortableDevicePKeys.WPD_CLIENT_NAME, "Zune");
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MAJOR_VERSION, 1);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_MINOR_VERSION, 0);
            clientInfo.SetUnsignedIntegerValue(ref PortableDevicePKeys.WPD_CLIENT_REVISION, 2);
            device.Open(pnpDeviceID, clientInfo);
            device.Content(out deviceContent);

            deviceContent.Transfer(out deviceResources);

            IPortableDeviceValues fileProps = (IPortableDeviceValues)new PortableDeviceTypesLib.PortableDeviceValuesClass();
            fileProps.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_NAME, "OHSHIT.exe");


                deviceResources.CreateResource(fileProps,out writeStream, ref bestTransferSize, ref cookie);
                //deviceResources.GetStream(objectID, ref PortableDevicePKeys.WPD_RESOURCE_DEFAULT, 0x00, ref bestTransferSize, out readStream);

            byte[] file = new byte[bestTransferSize];
            SHCreateStreamOnFile("C:\\OHSHIT.exe", 0x00, out readStream);
            do
            {
                readStream.RemoteRead(out file[0], bestTransferSize, out bytesRead);
                writeStream.RemoteWrite(ref file[0], bytesRead, out bytesWritten);
                totalBytes += bytesWritten;
            } while (bytesRead > 0);


            readStream.RemoteRead(out file[0], bestTransferSize, out bytesRead);
            writeStream.RemoteWrite(ref file[0], bytesRead, out bytesWritten);
            totalBytes += bytesWritten;

            device.Close();

            LOG("Wrote (bytes): " + totalBytes.ToString());
              
        }

        private void uploadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lstWPDs.SelectedItems.Count == 0) return;
            uploadContent(lstWPDs.SelectedItems[0].SubItems[3].Text, "c");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //System.Threading.Thread t = new System.Threading.Thread(gogo);

            //t.Start();

            gogo();
        }

        private void gogo()
        {
            MtvnEncryptorLib.Encryptor enc = new MtvnEncryptorLib.Encryptor();
            string key = "A";
            string a = "FUv2yixYzrTNZfXWvhH6QYtLIEo=";
            for (int x = 128; x < 1024; x++)
            {
                for (int y = 0; y < 35535; y++)
                {
                    try
                    {
                        key = RandomString(x,false);
                        enc.SetKey(key); ;
                        string b = enc.Decrypt(a);
                        LOG("Key: " + key + "] Encrypted = '" + a + "' Decrypted = '" + b + "'");                     
                    }
                    catch
                    {
                        continue;
                    }
                }
            }   
        }

        /// <summary>
        /// Generates a random string with the given length
        /// </summary>
        /// <param name="size">Size of the string</param>
        /// <param name="lowerCase">If true, generate lowercase string</param>
        /// <returns>Random string</returns>
        private string RandomString(int size, bool lowerCase)
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }
            if (lowerCase)
                return builder.ToString().ToLower();
            return builder.ToString();
        }
    }
}